package logic

import (
	"context"
	"encoding/json"
	"fmt"
	"time"

	"googee/common/errorx"
	"googee/common/utils"
	"googee/service/account/rpc/account"
	"googee/service/task/api/internal/svc"
	"googee/service/task/api/internal/types"
	"googee/service/task/model"

	"github.com/dtm-labs/dtmcli/dtmimp"
	"github.com/dtm-labs/dtmgrpc"
	"github.com/jinzhu/copier"
	"github.com/zeromicro/go-zero/core/logx"
	"github.com/zeromicro/go-zero/core/stores/sqlx"
)

type RequireLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewRequireLogic(ctx context.Context, svcCtx *svc.ServiceContext) *RequireLogic {
	return &RequireLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *RequireLogic) Require(req *types.RequireReq) (resp *types.RequireReply, err error) {

	resp = &types.RequireReply{}

	id, err := l.ctx.Value("userId").(json.Number).Int64()
	if err != nil {
		return nil, err
	}

	//获得所有配置数据的内容
	conditions, err := l.svcCtx.ConditionConfigModel.FindAll(l.ctx)
	if err != nil {
		return nil, errorx.NewCodeErrorNoMsg(errorx.TASK_ERROR + 2)
	}

	//生成cond map表
	cond_map := make(map[string]string)
	for _, cond := range conditions {
		cond_map[cond.Name] = cond.Desc
	}

	//获得当前分组所有配置的条件
	task_conds_data := []*types.TaskCondition{}
	task_conds, err := l.svcCtx.TaskConditionModel.FindGroupConditonsByTaskId(l.ctx, req.TaskId)
	if err != nil {
		return nil, errorx.NewCodeErrorNoMsg(errorx.TASK_ERROR + 2)
	}
	copier.Copy(&task_conds_data, task_conds)

	//生成配置表
	task_conds_map := make(map[int64]*model.TaskCondition)
	for _, cond := range task_conds {
		task_conds_map[cond.Id] = cond
	}

	task, err := l.svcCtx.TaskModel.FindOne(l.ctx, req.TaskId)
	if err != nil {
		return nil, errorx.NewCodeErrorNoMsg(errorx.TASK_ERROR + 1)
	}

	//获得任务分组的信息
	taskGroup, err := l.svcCtx.TaskGroupModel.FindOne(l.ctx, task.GroupId)

	if err != nil {
		return nil, errorx.NewCodeErrorNoMsg(errorx.TASK_ERROR + 1)
	}

	now := time.Now()

	//计算当前的batch id 和上一次的batch id,周期性的奖励最多只能保存1次未领，超过一次的不算
	var batch_id int64 = req.BatchId
	var next_batch_id int64 = 1
	if taskGroup.Typ == "Y" {
		batch_id_t := utils.NextCronTime(taskGroup.Cron, now)
		next_batch_id = batch_id_t.Unix()
	}
	task_count_map, err := getOneTaskCountMap(l.svcCtx.SqlConn, l.ctx, task.GroupId, req.TaskId, next_batch_id, batch_id, id)
	if err != nil {
		return nil, err
	}

	logx.Infof("task_count_map: %v", task_count_map)

	//获得任务的领取记录，本次和上一次
	//获得以前是否领取记录，只算前两次的
	required_status, err := l.svcCtx.TaskStatusModel.FindAllGroupTaskStatus(l.ctx, task.GroupId, next_batch_id, batch_id, id)
	switch err {
	case sqlx.ErrNotFound:
		break
	case nil:
		break
	default:
		return nil, errorx.NewCodeError(errorx.INTERNAL_ERROR, fmt.Sprintf("errx :%v", err.Error()))
	}
	//生成已领取的hash map 用来做排他处理
	req_status_map := make(map[string]bool)
	for _, s := range required_status {
		k := fmt.Sprintf("%v-%v-%v", s.GroupId, s.TaskId, s.BatchId)
		req_status_map[k] = true
	}
	logx.Infof("领取奖励的映射表: %v", req_status_map)

	//检查当前的领取的任务是否已经领取
	{
		complete := isComplete(task.Id, req.BatchId, task_count_map, task_conds_map)
		logx.Infof("当前任务是否完成: %v", complete)
		if !complete {
			return nil, errorx.NewCodeErrorNoMsg(errorx.TASK_ERROR + 3)
		}
	}

	//检查当前要领取的任务是否已经完成
	{
		k := fmt.Sprintf("%v-%v-%v", task.GroupId, task.Id, req.BatchId)
		if _, ok := req_status_map[k]; ok {
			return nil, errorx.NewCodeErrorNoMsg(errorx.TASK_ERROR + 4)
		}
	}

	//获得当前任务的奖励数据
	bonus, err := l.svcCtx.TaskBonusModel.FindAllTaskBonus(l.ctx, task.Id)
	if err != nil {
		return nil, errorx.NewCodeErrorNoMsg(errorx.INTERNAL_ERROR)
	}

	//领取奖励
	{
		result, err := l.svcCtx.TaskStatusModel.Insert(l.ctx, &model.TaskStatus{
			GroupId: task.GroupId,
			TaskId:  task.Id,
			BatchId: req.BatchId,
			UserId:  id,
			Status:  1,
		})

		if err != nil {
			return nil, errorx.NewCodeErrorNoMsg(errorx.INTERNAL_ERROR)
		}

		n, err := result.RowsAffected()
		if err != nil {
			return nil, errorx.NewCodeErrorNoMsg(errorx.INTERNAL_ERROR)
		}

		if n > 0 {
			accountRpcBusiServer, err := l.svcCtx.Config.Account.BuildTarget()

			if err != nil {
				return nil, errorx.NewCodeErrorNoMsg(errorx.INTERNAL_ERROR)
			}

			//调用dtm给account微服务发送奖励
			for _, b := range bonus {
				gid := dtmgrpc.MustGenGid(l.svcCtx.Config.DtmServer)
				msg := dtmgrpc.NewMsgGrpc(l.svcCtx.Config.DtmServer, gid).Add(
					accountRpcBusiServer+"/account.Account/addAccount", &account.IdAddRequest{
						Id:     id,
						Field:  b.Name,
						Amount: b.Count,
					})

				err = msg.Submit()
				dtmimp.FatalIfError(err)
			}
		}
	}

	//重新计算当前任务的状态
	{
		copier.Copy(&resp.Data, task)
		complete := isComplete(task.Id, next_batch_id, task_count_map, task_conds_map)
		copier.Copy(&resp.Data.Bonus, bonus)
		copier.Copy(&resp.Data.Conditions, task_conds)
		resp.Data.Completed = complete
		resp.Data.BatchId = next_batch_id

		//获得任务的领取记录，本次和上一次
		//获得以前是否领取记录，只算前两次的
		required_status, err := l.svcCtx.TaskStatusModel.FindAllGroupTaskStatus(l.ctx, task.GroupId, next_batch_id, batch_id, id)
		switch err {
		case sqlx.ErrNotFound:
			break
		case nil:
			break
		default:
			return nil, errorx.NewCodeError(errorx.INTERNAL_ERROR, fmt.Sprintf("errx :%v", err.Error()))
		}
		//生成已领取的hash map 用来做排他处理
		req_status_map := make(map[string]bool)
		for _, s := range required_status {
			k := fmt.Sprintf("%v-%v-%v", s.GroupId, s.TaskId, s.BatchId)
			req_status_map[k] = true
		}

		k := fmt.Sprintf("%v-%v-%v", task.GroupId, task.Id, next_batch_id)
		if _, ok := req_status_map[k]; ok {
			resp.Data.Status = 1
		}
	}

	return resp, nil
}
